(function($){
      $.fn.mlm_lookup = function(options) {
        // build main options before element iteration
        var aSelected, i;            

       options = $.extend({
        	  collapse    : false, // only show first node of fist layer
            collapseLeaf: true,  // collapseLeaf, show leaf node in a row
            cbLeafOnly  : true,
            nodes       : new Object(), // nodes['n'?] is array of object , nodes['c'?'] is array of child node id
            multiple    : true,
            for_php     : true,
            hSelected   : {},    // array of selected id
        }, options);

        if (options.multiple && options.for_php){
        	options.oname = options.name; //original name
          options.name +='[]';
        }

        if (options.selected != ''){    // selected value is comma separated string, find all default value
          aSelected = options.selected.split(',');
          for (i=0; i<aSelected.length;i++){
            options.hSelected[aSelected[i]]=1; //selected
          }
        }

        if (options.data){
          addnode(options.data, options);
          buildnode($(this),0, options);
        }

	      // handle expand/collapse
	      //<ul class="checkboxTree" id="BOX_ml_mlookupcity">
	      //  <li id="cityc_1"><div class="mlmicon"><span>+</span>Chinese</div> ... </li>
	      //</ul>
	      this.find('div.mlmicon').bind("click", function(e, a){
	        $(this).parent().children('ul').toggle();
	
	        temp = $(this).find('span.icon').html();
	        temp = temp == '+' ? '-' : '+';
	        $(this).find('span.icon').html(temp);
	        //custom image for collapse / expand, pls refer to checkboxtree.js
	      }); // click function for expand

      };


      this.addnode = function(aArray, options){
        var  name, node, child,i;
        //access js object option
        name = options.oname;
        for (i = 0; i < aArray.length; i=i + 3){
          node       = new Object();
          node.id    = aArray[i];
          node.topid = aArray[i+1];
          node.name  = aArray[i+2];

          // use and array of object to store all nodes (internal representation inside this class) 
          options.nodes[name+'n'+aArray[i]] = node; 

          // add self node id to parent
          if (!options.nodes.hasOwnProperty(name+'c'+aArray[i+1])){
            child = [];
          } else {
            child = options.nodes[name+'c'+aArray[i+1]]; // get the array storing the list of child
          }

          child.push(node.id);
          options.nodes[name+'c'+aArray[i+1]] = child;
        }
      }; // addnode function
      
      // check if it's child has checked value, expand it by default
      this.child_checked = function(node_id, options){
        var name, a_child_node, i;
        
        name     = options.oname;
        a_child_node = options.nodes[name+'c'+node_id]; // find all child_id of this node
        if (typeof a_child_node == 'undefined'){ // this is not a valid node
          return false;
        }
        
        if ( options.hSelected[node_id] ){
        	return true;
        }
        
        for (i = 0; i < a_child_node.length; i++){   	
          if ( options.hSelected[ a_child_node[i] ] ){
            return true;
          } 
          
          if ( child_checked( a_child_node[i], options) ) {
          	return true;
          }
        }
        return false;
      }
  
      // all nodes are created in addnode function, now build it in tree structure
      this.buildnode = function(topnode, node_id, options){
        var name, a_child_node, temp_leaf_node, i, child_id, aChild
        name     = options.oname;
        a_child_node = options.nodes[name+'c'+node_id]; // find all child_id of this node
         temp_leaf_node = []; // child leaf node

        for ( i = 0; i < a_child_node.length; i++){
          child_id = a_child_node[i];
          // depth first search.. search one with child
          if (options.nodes.hasOwnProperty(name+'c'+child_id)){ // has child node
            aChild = options.nodes[name+'c'+child_id];
            topnode.append( format_child(child_id, options, aChild.length) );
            buildnode($('#'+name+'n_'+child_id), child_id, options);
          } else {
            temp_leaf_node.push(child_id);
          }
        }

        // This loop handles leaf node only
        for (i=0; i< temp_leaf_node.length; i++){
          child_id = temp_leaf_node[i];
          topnode.append(format_child(child_id, options, 0))
        }

        return;
      }; // buildnode function

      this.li = function(content, tag_id, tag_class){
      	tag_id    = tag_id    == '' ? '' : ' id="'    + tag_id   + '"';
      	tag_class = tag_class == '' ? '' : ' class="' + tag_class+ '"';
      	return '<li '+tag_id+tag_class+'>'+content+"</li>\n";
      };


    
      // format child 
      //   return 
      this.format_child = function(node_id, options, n_child){
        var name = options.oname,
            cbLeafOnly = options.cbLeafOnly, //only has check box on leave node
            collapse   = options.collapse,
            item_id    = options.nodes[name+'n'+node_id].id,
            item_label = options.nodes[name+'n'+node_id].name,
            form_var_name = options.name,
            selected, cb_html, child_ul, icon, tag_class;

        selected = '';
        
        if (options.hSelected[node_id]){
          selected = ' checked="checked"'; // the 'html' code, add for selected node
          item_label = '<em style="color:red;">'+item_label+'</em>';
        }
        cb_html = '<input type=\"checkbox\" name="'+form_var_name+'" value="'+item_id+'"'+selected+'>';
        if (options.multiple != true){
           cb_html  = '<input type=\"radio\" name="'+form_var_name+'" value="'+item_id+'"'+selected+'>';
        }
        if (cbLeafOnly && n_child>0){
        	cb_html = '';
        }

        if (n_child > 0){
          child_ul = '<UL id='+name+'n_'+node_id+'>'+'</UL>';
          if (collapse && !child_checked(node_id, options)){	
            child_ul   = '<UL id='+name+'n_'+node_id+' style="display:none;" >'+'</UL>';
          }
          icon = collapse ? '+' : '-';
          return this.li('<div class="mlmicon"><span class="mlmicon">' + icon + '</span>'+ cb_html + item_label
                    + '(' + n_child + ')' +'</div>' + child_ul, name + 'c_' + node_id, '');
        } else { // no child
          tag_class = options.collapseLeaf ? 'leaf' : '';
          return this.li(cb_html+item_label, name+'c_'+node_id, tag_class); //'<span class="leaf"></span>'+
        }
        
      }; //format_child;


})(jQuery);
